import time
from .services import CozeResumeService
from .serializers import ResumeChatSerializer, ResumeChatSessionSerializer


from cozepy import Coze, TokenAuth, Message, ChatEventType, MessageObjectString
import time
import logging
from io import BytesIO
from django.http import StreamingHttpResponse, HttpResponse
from rest_framework.views import APIView
from rest_framework.exceptions import ValidationError
from rest_framework import status
from rest_framework.response import Response
import requests

from .models import ResumeChatSession, ResumeChatMessage
from .services import CozeResumeService
from .serializers import ResumeChatSerializer
from user.models import SysUser
from cozepy import Message, MessageObjectString

class ResumeChatView(APIView):
    """简历助手流式聊天接口（保留图片上传，仅传递解析后的文件文本）"""

    def __init__(self, **kwargs):
        super().__init__(** kwargs)
        self.coze_service = CozeResumeService()
        self.logger = logging.getLogger(__name__)

    def upload_image_to_coze(self, image_url):
        """保留图片上传逻辑（不变）"""
        try:
            response = requests.get(image_url, timeout=10)
            response.raise_for_status()
            image_stream = BytesIO(response.content)
            file = self.coze_service.coze.files.upload(file=image_stream)
            self.logger.info(f"图片上传成功，file_id: {file.id}")
            return file.id
        except Exception as e:
            self.logger.error(f"图片上传失败: {str(e)}", exc_info=True)
            raise ValueError(f"图片处理失败: {str(e)}")

    def post(self, request):
        # 1. 验证请求数据
        serializer = ResumeChatSerializer(data=request.data)
        if not serializer.is_valid():
            raise ValidationError(serializer.errors)

        # 2. 提取参数（移除file_id相关处理）
        prompt = serializer.validated_data["prompt"]
        user_id = serializer.validated_data["user_id"]
        resume_text = serializer.validated_data.get("resume_text", "").strip()
        resume_filename = serializer.validated_data.get("filename", "")
        image_url = serializer.validated_data.get("image_url", "").strip()

        # 3. 日志记录（移除file_id日志）
        self.logger.info(f"用户需求: {prompt}")
        self.logger.info(f"简历文本长度: {len(resume_text)} 字符")
        self.logger.info(f"图片URL: {image_url if image_url else '无'}")

        # 4. 验证用户（不变）
        try:
            user = SysUser.objects.get(id=user_id)
        except SysUser.DoesNotExist:
            return HttpResponse("用户不存在", status=400)

        # 5. 创建会话（不变）
        session_title = prompt[:50] if prompt else "空会话"
        chat_session = ResumeChatSession.objects.create(
            user=user,
            title=session_title,
            resume_filename=resume_filename,
            resume_text=resume_text
        )

        # 6. 保存用户消息（不变）
        user_message = ResumeChatMessage.objects.create(
            session=chat_session,
            sender='user',
            content=prompt
        )

        # 7. 构造最终Prompt（仅包含解析后的文本）
        # 7. 构造最终Prompt（仅包含解析后的文本）
        if resume_text:
            final_prompt = (
                # f"以下是用户简历的文本内容（对应原文件：{resume_filename}）：\n"
                # f"【简历文本】\n{resume_text}\n\n"
                # f"用户当前需求：{prompt}\n\n"
                # "请基于上述简历内容，针对性回复用户需求。"
                f"{resume_text}"
            )
            # 验证简历文本已正确传入
            self.logger.info(f"构造的最终Prompt包含简历文本，长度：{len(resume_text)}")
        else:
            final_prompt = prompt
            self.logger.warning("未收到简历文本，仅传递用户需求")

        # 8. 处理图片上传（保留图片逻辑）
        image_file_id = None
        if image_url:
            try:
                image_file_id = self.upload_image_to_coze(image_url)
            except ValueError as e:
                return HttpResponse(str(e), status=400)

        # 9. 构建消息对象（仅包含文本+图片，无文件）
        # message_objects = [MessageObjectString.build_text(final_prompt)]
        message_objects = [MessageObjectString.build_text(final_prompt)]
        if image_file_id:  # 只处理图片的file_id
            message_objects.append(MessageObjectString.build_image(file_id=image_file_id))

            additional_messages = [
                Message.build_user_question_objects(message_objects)
            ]
        elif not image_file_id:
            additional_messages = [
                Message.build_user_question_objects(message_objects)
            ]




        # 10. 流式响应生成器（不变）
        def stream_generator():
            ai_response = []
            start_time = time.time()

            try:
                for event in self.coze_service.coze.chat.stream(
                        bot_id=self.coze_service.bot_id,
                        user_id=user_id,
                        additional_messages=additional_messages,
                        timeout=30,
                ):
                    if event.event == ChatEventType.ERROR:
                        error_msg = event.data.get("msg", "Coze服务错误")
                        self.logger.error(f"Coze错误: {error_msg}")
                        yield f"[ERROR]{error_msg}"
                        return
                    elif event.event == ChatEventType.CONVERSATION_MESSAGE_DELTA:
                        if event.message.content.strip():
                            ai_response.append(event.message.content)
                            yield event.message.content
                    elif event.event == ChatEventType.CONVERSATION_CHAT_COMPLETED:
                        yield "[DONE]"

                # 保存AI回复
                end_time = time.time()
                response_time = round(end_time - start_time, 2)
                tokens_used = len(''.join(ai_response)) // 4
                if ai_response:
                    ResumeChatMessage.objects.create(
                        session=chat_session,
                        sender='ai',
                        content=''.join(ai_response),
                        tokens_used=tokens_used,
                        response_time=response_time
                    )

            except Exception as e:
                self.logger.error(f"流式调用异常: {str(e)}", exc_info=True)
                yield f"[ERROR]{str(e)}"

        # 11. 返回流式响应（不变）
        return StreamingHttpResponse(
            stream_generator(),
            content_type="text/plain; charset=utf-8"
        )





# 1. 先修正导入（关键：导入正确的 io 模块，处理文件流）
import io
from rest_framework.parsers import MultiPartParser
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
import fitz  # PyMuPDF 解析 PDF
import docx  # python-docx 解析 Word（仅支持 .docx，不支持 .doc）
# 若需支持 .doc 格式，需额外安装 python-docx2txt：pip install python-docx2txt
# import docx2txt

from .serializers import ResumeUploadSerializer  # 导入已定义的序列化器


class UploadResumeView(APIView):
    parser_classes = [MultiPartParser]  # 支持接收 multipart/form-data 格式文件
    # 限制文件大小：10MB（与前端一致）
    MAX_FILE_SIZE = 10 * 1024 * 1024  # 10MB

    def post(self, request):
        # 1. 用序列化器验证文件是否存在（避免手动取 request.FILES 导致的错误）
        serializer = ResumeUploadSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)  # 验证失败会自动返回400错误
        file_obj = serializer.validated_data['file']

        # 2. 校验文件大小
        if file_obj.size > self.MAX_FILE_SIZE:
            return Response(
                {"detail": f"文件过大（{file_obj.size/1024/1024:.2f}MB），仅支持10MB以内的PDF/Word文件"},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 3. 校验文件类型（后缀）
        file_name = file_obj.name
        file_ext = file_name.split('.')[-1].lower() if '.' in file_name else ''
        valid_exts = ['pdf', 'docx', 'doc']  # 仅支持这三种格式
        if file_ext not in valid_exts:
            return Response(
                {"detail": f"不支持的文件格式（{file_ext}），仅支持 PDF、Word（.doc/.docx）"},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 4. 解析文件文本（核心逻辑，加异常捕获）
        resume_text = ""
        try:
            # 读取文件流（避免直接读文件导致的内存问题）
            file_stream = io.BytesIO(file_obj.read())

            if file_ext == 'pdf':
                # 解析 PDF
                pdf_doc = fitz.open(stream=file_stream, filetype='pdf')
                resume_text = "\n".join([page.get_text().strip() for page in pdf_doc if page.get_text().strip()])
                pdf_doc.close()

            elif file_ext == 'docx':
                # 解析 .docx
                doc = docx.Document(file_stream)
                resume_text = "\n".join([p.text.strip() for p in doc.paragraphs if p.text.strip()])

            elif file_ext == 'doc':
                # 解析 .doc（需安装 python-docx2txt，python-docx 不支持 .doc）
                # 注意：python-docx2txt 依赖 antiword（Windows需手动安装，Mac/Linux用 brew install antiword 或 apt install antiword）
                # resume_text = docx2txt.process(file_stream)
                return Response(
                    {"detail": ".doc 格式需额外安装依赖（python-docx2txt + antiword），建议优先使用 .docx 或 PDF 格式"},
                    status=status.HTTP_400_BAD_REQUEST
                )

            # 校验解析结果（避免空文本）
            if not resume_text.strip():
                return Response(
                    {"detail": "文件解析成功，但未提取到有效文本（可能是扫描件PDF或空白文件）"},
                    status=status.HTTP_400_BAD_REQUEST
                )

        except Exception as e:
            # 捕获解析异常（如损坏的文件、加密PDF等）
            return Response(
                {"detail": f"文件解析失败：{str(e)}（可能是文件损坏或格式不兼容）"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

        # 5. 返回解析结果（前端需用 data.text 和 data.filename）
        return Response({
            "text": resume_text,  # 解析后的简历文本
            "filename": file_name  # 原文件名
        }, status=status.HTTP_200_OK)


class ChatHistoryView(APIView):
    """简历助手历史记录管理接口"""

    def get(self, request):
        """获取用户的所有会话历史记录"""
        user_id = request.query_params.get('user_id')
        if not user_id:
            return Response(
                {"detail": "缺少user_id参数"},
                status=status.HTTP_400_BAD_REQUEST
            )

        try:
            user = SysUser.objects.get(id=user_id)
            sessions = ResumeChatSession.objects.filter(user=user).order_by('-updated_at')
            serializer = ResumeChatSessionSerializer(sessions, many=True)
            return Response(serializer.data)
        except SysUser.DoesNotExist:
            return Response(
                {"detail": "用户不存在"},
                status=status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return Response(
                {"detail": f"获取历史记录失败：{str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

    def post(self, request):
        """保存当前对话为历史记录"""
        user_id = request.data.get('user_id')
        title = request.data.get('title', '新对话')
        messages = request.data.get('messages', [])
        resume_filename = request.data.get('resume_filename', '')
        resume_text = request.data.get('resume_text', '')

        if not user_id:
            return Response(
                {"detail": "缺少user_id参数"},
                status=status.HTTP_400_BAD_REQUEST
            )

        try:
            user = SysUser.objects.get(id=user_id)

            # 创建会话
            session = ResumeChatSession.objects.create(
                user=user,
                title=title,
                resume_filename=resume_filename,
                resume_text=resume_text
            )

            # 保存消息
            for msg_data in messages:
                ResumeChatMessage.objects.create(
                    session=session,
                    sender=msg_data.get('sender', 'user'),
                    content=msg_data.get('content', '')
                )

            return Response(
                {"detail": "对话已保存", "session_id": session.id},
                status=status.HTTP_201_CREATED
            )
        except SysUser.DoesNotExist:
            return Response(
                {"detail": "用户不存在"},
                status=status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return Response(
                {"detail": f"保存对话失败：{str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

    def delete(self, request):
        """删除指定的历史会话"""
        session_id = request.data.get('session_id')
        user_id = request.data.get('user_id')

        if not session_id or not user_id:
            return Response(
                {"detail": "缺少session_id或user_id参数"},
                status=status.HTTP_400_BAD_REQUEST
            )

        try:
            user = SysUser.objects.get(id=user_id)
            session = ResumeChatSession.objects.get(id=session_id, user=user)
            session.delete()
            return Response({"detail": "会话已删除"}, status=status.HTTP_200_OK)
        except (SysUser.DoesNotExist, ResumeChatSession.DoesNotExist):
            return Response(
                {"detail": "用户或会话不存在"},
                status=status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return Response(
                {"detail": f"删除会话失败：{str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )